Commit a4d4f043 authored by Ali El Amrani's avatar Ali El Amrani

add readme

parent 27951fe8
# Mèmiscape Purescript
You can install the project using `yarn install`
## Mèmiscape Types
Mèmiscape is built using 7 parameters
3 types of Nodes (branch, group, period)
3 types of Edges (link, branch link, ancestor link)
1 frame (bounding box)
## Using Purescript to pre-process phylo data (json)
There is 2 main problems i've encountered regarding accessing data in a strongly-typed way :
* You have to define the JSON's shape for the compiler, that enables you to already take out some of the unnecessary information but if the JSON has a lot of `Maybe` values, you need to define a lot of cases to filter. Exemple in this case :
```haskell
instance JSON.ReadForeign PhyloObject where
readImpl f = do
{ from: mFrom, to:mTo, pos:mPos, support:mSupport, role:mRole, foundation:mFoundation, lbl:mLbl, weight:mWeight, branch_x: mBranch_x, branch_y: mBranch_y, label, bId:mBId,_gvid, nodeType: mNodeType} ::
{ from :: Maybe String, to :: Maybe String, pos :: Maybe String, support :: Maybe String, role :: Maybe String, foundation :: Maybe String, lbl :: Maybe String, weight :: Maybe String, branch_x :: Maybe String , branch_y :: Maybe String, label :: String, bId :: Maybe String ,_gvid :: Int, nodeType :: Maybe String } <- JSON.readImpl f
case mNodeType of
Nothing -> pure $ Default { _gvid }
Just nodeType ->
case nodeType of
"branch" ->
case mBranch_x of
Nothing -> pure $ Default { _gvid }
Just branch_x ->
case mBranch_y of
Nothing -> pure $ Default { _gvid }
Just branch_y ->
```
* The second problem comes after you've got all your data and cases sorted, you need to apply transformation to your data so it fits the D3 code used in Mèmiscape, for now those data transformations are handled via ffi in Javascript along with Mèmiscape
## Mesh D3 with Reactix
React Hooks are pretty cool when it comes to use D3 unlike Class Components. Most of the time you'll use `useRef()` to use D3 after React finished rendering the componenent.
Working with D3 and Reactix, you shouldn't forget to call d3 at least once, here's how it is called in `Main.purs` :
```haskell
import Graphics.D3.Base
d3charge :: D3
d3charge = d3
```
Without it, the page doesn't have the d3 object it needs to work properly. If you use D3 and React without calling d3 first, React will collapse. (I don't know why, you can check the issue there : https://gitlab.iscpif.fr/aelamrani/project-/issues/1)
## Affjax & Reactix/Toestand
To use Affjax inside of Reactix, you need to use `useEffect'` along with `LaunchAff_` & `LiftEffect`, this is also where Toestand comes in handy. Since we can store data inside a toestand box, we can use that as a condition to know if we get the correct value. An example can be found in the project Infos.purs file :
```haskell
infoCorpusCpt :: R.Component Props
infoCorpusCpt = R.hooksComponent "infoCorpus" cpt where
cpt { } _children = do
fetched <- T.useBox Nothing -- We store null data here
R.useEffect' $ do -- Launch Aff inside Effect to get PhyloJSON
launchAff_ $ do
mr <- PTE.fetchPhyloJSON
liftEffect $ do
case mr of
Nothing -> log "Nothing" -- In case of error
Just r -> T.write_ (Just r) fetched -- Store PhyloJSON
pure $ infoCorpusLoaded { fetched } [] -- Launch a new component with data inside
```
## Different ways to show data and ReadForeign
In the beginning, I used a simple type record to capture the json, but it proved quite messy when I needed to sort out what was what, but you can't use `newtypes` to represent objects or edges of the Mèmiscape, because newtype is for a single data constructor and if you use them to represent Mèmiscape's objects and edges, you'll need 3 for each.
```haskell
data PhyloObject = PhyloBranch -- Either that
{ branch_x :: String
, branch_y :: String
, label :: String
, bId :: String
, _gvid :: Int
, pos :: String
, nodeType :: String
} | PhyloGroup
{ from :: String
, to :: String
, pos :: String
, support :: String
, role :: String
, foundation :: String
, lbl :: String
, weight :: String
, bId :: String
, _gvid :: Int
, nodeType :: String
} | PhyloPeriod
{ _gvid :: Int
, nodeType :: String
} | Default
{
_gvid :: Int
}
type PhyloObject =
{ branch_x :: Maybe String
, branch_y :: Maybe String
, label :: Maybe String
, pos :: Maybe String
, from :: Maybe String
, to :: Maybe String
, support :: Maybe String
, role :: Maybe String
, foundation :: Maybe String
, lbl :: Maybe String
, weight :: Maybe String
, bId :: Maybe String
, nodeType :: Maybe String
, _gvid :: Int
}
```
This is 2 ways to represent data, the difference between them is just you'll need a way to deal with all those Maybe values but you might in both cases go with ReadForeign, we can see it being used in the intro. There should be better ways to do deal with it. The only difference I've seen so far in using newtype or data in Purescript is how the output changes in Javascript.
Here's the output of newtype :
```javascript=
var Branch = function (x) {
return x;
};
```
Here's the output of data :
```javascript
var Branch = (function () {
function Branch(value0) {
this.value0 = value0;
};
Branch.create = function (value0) {
return new Branch(value0);
};
return Branch;
```
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment