Skip to content
Snippets Groups Projects
Select Git revision
  • f81a5d25c749d70a2e08da74c31bcb49dcb63bee
  • main default protected
  • feat/improve
  • feat/hg-hub
  • gh-pages
  • fix/wrong-model
  • fix/consistent-storage-classname
  • feat/smoke-test-ci
  • ialacol-0.12.0
  • ialacol-0.11.5
  • ialacol-0.11.4
  • ialacol-0.11.3
  • ialacol-0.11.2
  • ialacol-0.11.1
  • ialacol-0.11.0
  • ialacol-0.10.4
  • ialacol-0.10.3
  • ialacol-0.10.2
  • ialacol-0.10.1
  • ialacol-0.10.0
  • ialacol-0.9.0
  • ialacol-0.8.0
  • ialacol-0.7.3
  • ialacol-0.7.2
  • ialacol-0.7.1
  • ialacol-0.7.0
  • ialacol-0.6.3
  • ialacol-0.6.2
28 results

get_llm.py

Blame
  • lab.tsx 12.51 KiB
    import * as React from 'react';
    import * as paper from "paper";
    import {StepManager} from "./ui/steps/stepManager";
    import {LoadPictureStep} from "./ui/steps/loadPictureStep";
    import {RulerStep} from "./ui/steps/rulerStep";
    import {Badge, Button, ButtonGroup, Col, Container, Form, Navbar, Row} from "react-bootstrap";
    import {Ruler} from "./instruments/ruler";
    import {PlacePetriDishStep} from "./ui/steps/placePetriDishStep";
    import {PetriDish} from "./instruments/petriDish";
    import {DrawBlobMaskStep} from "./ui/steps/drawBlobMaskStep";
    import {BlobMask} from "./instruments/blobMask";
    import {VectorCoords} from "./data/coords/vectorCoords";
    import {PathCoords} from "./data/coords/pathCoords";
    import {DownloadStep} from "./ui/steps/downloadStep";
    import {PaperUtils} from "./utils/paperUtils";
    import {EllipseCoords} from "./data/coords/ellipseCoords";
    import {Welcome} from "./ui/welcome";
    import {DataImporter} from "./data/dataImporter";
    import {WorkInfo} from "./data/work/workInfo";
    import {IoUtils} from "./utils/ioUtils";
    import {WorkInfoParser} from "./data/work/process/workInfoParser";
    
    /**
     * Debug mode (ou pas)
     */
    export const DEBUG_MODE = false;
    
    /**
     * La taille par défaut de la règle
     */
    export const DEFAULT_RULER_TICK_COUNT = 8;
    
    /**
     * La taille minimum de la règle
     */
    export const MIN_RULER_TICK_COUNT = 8;
    
    /**
     * La taille maximum de la règle
     */
    export const MAX_RULER_TICK_COUNT = 15;
    
    
    export interface LabData {
    
        pictureSize : paper.Size,
    
        filename : string,
    
        workInfo : WorkInfo,
    
        rulerTickCount : number,
    
        rulerCoords : VectorCoords,
    
        petriDishCoords : EllipseCoords,
    
        blobMaskCoords : PathCoords
    }
    
    
    /**
     * Le lab
     */
    export class Lab extends React.Component<{}> {
    
        /**
         * Récolte des données
         */
        public data : LabData | null;
    
        /**
         * Le canvas sur lequel est dessiné la photo
         */
        private canvas : HTMLCanvasElement | null = null;
    
        /**
         * Le canvas sur lequel est dessiné la photo
         */
        private welcome = React.createRef<Welcome>();
    
        /**
         * La photo du blob
         */
        public raster : null | paper.Raster = null;
    
        /**
         * La règle
         */
        public ruler: Ruler;
    
        /**
         * La boîte de petri
         */
        public petriDish: PetriDish;
    
        /**
         * Le contour du blob
         */
        public blobMask: BlobMask;
    
        /**
         * Outil d'import de données
         */
        public dataImporter = new DataImporter();
    
        /**
         * Parsing du work in progress
         */
        public workInfoParser = new WorkInfoParser();
    
        public constructor(props : {}) {
            super(props);
        }
    
        /**
         * Post-init lorsque le lab est affiché
         */
        public componentDidMount() {
            if(this.canvas == null) {
                throw new Error("Canvas should have been initiated");
            }
    
            paper.setup(this.canvas);
            new paper.Tool();
            paper.tool.activate();
    
            // Ajout du zoom avec la molette
            this.canvas.addEventListener('wheel', (event) => {
                let target = paper.view.viewToProject(new paper.Point(event.offsetX, event.offsetY));
                if (event.deltaY > 0) {
                    this.zoomOut(target);
                } else {
                    this.zoomIn(target);
                }
            });
    
            // Ajout des déplacements
            paper.tool.onKeyDown = (event : paper.KeyEvent) => {
                if(event.key == "control") {
                    PaperUtils.changeCursor("move");
                }
            }
            paper.tool.onKeyUp = (event : paper.KeyEvent) => {
                if(event.key == "control") {
                    PaperUtils.changeCursor(null);
                }
            }
            paper.tool.onMouseDrag = function(event) {
                if(event.modifiers.control) {
                    let delta = event.point.subtract(event.downPoint);
                    paper.view.center = paper.view.center.subtract(delta);
                    event.preventDefault();
                }
            }
    
            // Prise en compte du redimensionnement navigateur (ou agrandissement/retrécissement de la vue)
            paper.view.onResize = (event) => {
                if(this.raster != null) {
                    paper.view.center = this.raster.position;
                }
            }
        }
    
        /**
         * Lance une nouvelle session de travail
         */
        public new(image : HTMLImageElement, filename : string) : boolean {
            console.info("Nouvelle session de travail")
            let workInfo = this.workInfoParser.parse(IoUtils.basename(filename));
    
    	// Disable this check to allow any filename
            /*
    	if(workInfo == null) {
                window.alert("Le nom du fichier ne respecte pas nomenclature")
                return false;
    	}
            */
    
            if(this.raster != null) {
                if(window.confirm("Écraser le travail en cours ?")) {
                    this.reset();
                } else {
                    return false;
                }
            }
    
            // Masque le composant d'accueil
            this.welcome.current.setState({visible: false });
    
            // Init du Raster de l'image
            this.raster = new paper.Raster();
            this.raster.image = image;
            this.raster.bounds.point = new paper.Point(0, 0);
            this.raster.smoothing = 'off';
    
            // Init des données
            let width = image.naturalWidth;
            let height = image.naturalHeight;
            this.data = {
                pictureSize: new paper.Size(width, height),
    
                filename: filename,
    
                workInfo: workInfo,
    
                rulerTickCount : DEFAULT_RULER_TICK_COUNT,
    
                rulerCoords: new VectorCoords(new paper.Point(width * 0.25, height / 2), new paper.Point(width * 0.75, height / 2)),
    
                petriDishCoords: new EllipseCoords(new paper.Point(width / 2, height / 2), width * 0.75 / 2, width * 0.75 / 2, 0),
    
                blobMaskCoords: new PathCoords(),
            };
    
            // Le plus en dessous en premier
            this.blobMask = new BlobMask(this, this.data.blobMaskCoords);
            this.petriDish = new PetriDish(this, this.data.petriDishCoords);
            this.ruler = new Ruler(this, this.data.rulerCoords);
    
            // Zoom global
            this.zoomFit();
    
            // Petit  refresh
            paper.view.update();
    
            return true;
        }
    
        /**
         * Remet à zéro l'espace de travail
         */
        private reset() : void {
            if(this.raster != null) {
                this.raster.remove();
            }
            this.raster = null;
    
            // Vidage des instruments
            this.ruler.clear();
            this.petriDish.clear();
            this.blobMask.clear();
    
        }
    
        /**
         * Zoom au plus près de la photo
         */
        public zoomFit() : void {
            if(this.raster != null && this.canvas != null && this.data.pictureSize != null) {
                this.zoomOn(new paper.Rectangle(0, 0, this.data.pictureSize.width, this.data.pictureSize.height))
            }
        }
    
        /**
         * Zoom sur une zone
         */
        public zoomOn(rectangle : paper.Rectangle, marginPercent : number = 0) {
            paper.view.center = rectangle.center;
            let xZoomFactor = Math.min(1, this.canvas.width / rectangle.width);
            let yZoomFactor = Math.min(1, this.canvas.height / rectangle.height);
            paper.view.zoom = Math.min(xZoomFactor, yZoomFactor) * (1 - marginPercent) / paper.view.pixelRatio;
            paper.view.update();
            this.onZoomChanged();
        }
    
        /**
         * Plus de zoom
         */
        public zoomIn(target? : paper.Point) : void {
            this.zoom(1.10, target);
        }
    
        // Zooms par delta
    
        /**
         * Moins de zoom
         */
        public zoomOut(target? : paper.Point) : void {
            this.zoom(0.90, target);
        }
    
        /**
         * Pas de zoom 1:1
         */
        public zoomNone() : void {
            paper.view.zoom = 1;
            this.onZoomChanged();
        }
    
        /**
         * Centralise le zoom
         */
        private zoom(zoomFactor : number, target? : paper.Point) {
            let oldZoom = paper.view.zoom;
            let newZoom = oldZoom * zoomFactor;
    
            if(target != undefined) {
                // let viewPosition = paper.view.viewToProject(target);
                let viewPosition = target;
                let mpos = viewPosition;
                let ctr = paper.view.center;
    
                let pc = mpos.subtract(ctr);
                let offset = mpos.subtract(pc.multiply(0.95 / zoomFactor)).subtract(ctr);
    
                paper.view.center = paper.view.center.add(offset);
            }
    
            // On borne les zooms pour ne pas que ça parte partout
            // Zoom minimum = zoom fit
            let minZoom =  0;
            if(this.data != null) {
                let xZoomFactor = Math.min(1, this.canvas.width / this.data.pictureSize.width)
                let yZoomFactor = Math.min(1, this.canvas.height / this.data.pictureSize.height);
                minZoom = Math.min(xZoomFactor, yZoomFactor)  / paper.view.pixelRatio;
            }
            let maxZoom =  10;
            paper.view.zoom = Math.min(maxZoom, Math.max(newZoom, minZoom));
            this.onZoomChanged();
        }
    
        /**
         * Appelé lorsque le zoom a changé
         */
        private onZoomChanged() {
            this.ruler?.refresh();
            this.petriDish?.refresh();
            this.blobMask?.refresh();
        }
    
        render(): React.ReactNode {
            return <Container fluid={true} className={"vh-100 d-flex flex-column"}>
                <Navbar bg="light" expand="lg" className={"p-0"}>
                    <Container fluid={true}>
                        <Row className={"col-md-12"}>
                            <div className="d-flex d-flex justify-content-between">
                                <Navbar.Brand href="./" className={"p-0"}><i className={"fa-solid fa-flask me-2"}></i>Blob Analysis Lab <sup><Badge pill bg="secondary" text="primary">école</Badge></sup></Navbar.Brand>
                                <Form className={"inline-form"}>
                                    <Form.Group controlId="zoomGroup">
                                        <Form.Label>Zoom :</Form.Label>
                                        <ButtonGroup aria-label="Zoom" className={"ms-2"}>
                                            <Button onClick={() => this.zoomIn()} variant={"primary"} size={"sm"}><i className="fa-solid fa-magnifying-glass-plus"></i></Button>
                                            <Button onClick={() => this.zoomOut()} variant={"primary"} size={"sm"}><i className="fa-solid fa-magnifying-glass-minus"></i></Button>
                                            <Button onClick={() => this.zoomFit()} variant={"primary"} size={"sm"}><i className="fa-regular fa-image"></i></Button>
                                            <Button onClick={() => this.zoomNone()} variant={"primary"} size={"sm"}>1:1</Button>
                                        </ButtonGroup>
                                        <Form.Label className={"ms-3"}>[CTRL] + <i className="fa-solid fa-computer-mouse"></i> = <i className="fa-solid fa-arrows-up-down-left-right"></i></Form.Label>
                                    </Form.Group>
                                </Form>
                                <div>
                                    <Button href={"docs/index.html"} target="_blank" variant={"primary"} size={"sm"}>Tutoriel<i className="ms-2 fa-solid fa-book"></i></Button>
                                </div>
                            </div>
                        </Row>
                    </Container>
                </Navbar>
                <Row className="flex-grow-1">
                    <div className="col position-relative">
                       <Welcome ref={this.welcome}/>
                        <canvas ref={(canvas : HTMLCanvasElement)=> this.canvas = canvas} data-paper-resize="false"  className="h-100 w-100 d-block" onContextMenu={() => false}></canvas>
                    </div>
                    <Col md={4} className={"border-2"}  >
                        <div className="mb-3">
                            <StepManager>
                                <LoadPictureStep lab={this} code="loadPicture" title="Charger une photo"/>
                                <RulerStep lab={this} code="placeRuler" title="Positionner la règle"/>
                                <PlacePetriDishStep  lab={this} code="placePetriDish" title="Positionner la boîte de petri"/>
                                <DrawBlobMaskStep  lab={this} code="drawBlobMask" title="Détourer le blob"/>
                                <DownloadStep  lab={this} code="download" title="Voir les résultats"/>
                            </StepManager>
                        </div>
                    </Col>
                </Row>
            </Container>
        }
    }